import os, sys
from Sanae3D.lib.ModelObject import Model3D
from Sanae3D.lib.StructReader import StructReader

class Vindictus_BSP(Model3D):
    
    HEADER_LUMPS = 64
    MAX_MAP_VERTS = 65536
    
    def __init__(self, obj3D=None, outFile=None, inFile=None):
        
        super(Vindictus_BSP,self).__init__("XAC")
        self.obj3D = obj3D
        self.inFile = inFile
        self.outFile = outFile
        self.lumps = []
        self.edges = {}
        self.surfedges = {}
        
    def parse_lumps(self):
        
        for i in range(self.HEADER_LUMPS):
            offset, size, version = self.inFile.read_long(3)
            lumpID = self.inFile.read_char(4)
            
            lump = [offset, size, version, lumpID]
            self.lumps.append(lump)
            
    def get_lump(self, lumpNum):
        
        lump = self.lumps[lumpNum]
        return lump[0], lump[1]
    
    def parse_normals(self, meshName):
        '''Normals stored in lump 30'''
        
        offset, size = self.get_lump(3)
        self.inFile.seek(offset)
        
        numNorms = size / 12
        print "%d normals" %numNorms
        
    def parse_normal_index(self, meshName):
        '''Normal indices stored in lump 31'''
        
        offset, size = self.get_lump(31)
        self.inFile.seek(offset)
        
        print size, offset
        numIndex = size / 4
        print "%d normal indices" %numIndex
        for i in range(numIndex):
            self.inFile.read_long()
            
    def parse_vertices(self, meshName):
        '''Vertices stored in lump 3'''
        
        offset, size = self.get_lump(3)
        self.inFile.seek(offset)
        
        numVerts = size / 12
        print "%d vertices" %numVerts
        for i in range(numVerts):
            vx, vy, vz= self.inFile.read_float(3)
            
            self.create_vertex(meshName, i)
            self.add_coords(meshName, i, [vx, vy, vz])
            
    def parse_edges(self, meshName):
        '''edges stored in lump 12'''

        offset, size = self.get_lump(12)
        self.inFile.seek(offset)
        
        self.edges[meshName] = []
        
        numEdges = size / 8
        print "%d edges" %numEdges, offset
        for i in range(numEdges):
            v1, v2 = self.inFile.read_long(2, sign=0)
            self.edges[meshName].append([v1, v2])
            
    def parse_surfedges(self, meshName):
        '''surface edges lump 13'''
        
        offset, size = self.get_lump(13)
        self.inFile.seek(offset)
        
        self.surfedges[meshName] = []
        
        numSurfedges = size / 4
        print "%d surface edges" %numSurfedges, offset
        for i in range(numSurfedges):
            self.surfedges[meshName].append(self.inFile.read_long())
            
    def get_verts(self, meshName, face):
        
        edges = self.edges[meshName]
        verts = set()
        for edge in face:
            verts.add(edges[abs(edge)][0])
            verts.add(edges[abs(edge)][1]) 
        print verts
        return list(verts)
            
    def parse_faces(self, meshName):
        '''faces, lump 7'''
        
        offset, size = self.get_lump(27)
        self.inFile.seek(offset)
        surfedges = self.surfedges[meshName]
        
        numFaces = size / 72
        print "%d faces" %numFaces
        
        for i in range(numFaces):
            planeNum = self.inFile.read_long(sign=0)
            side, onNode = self.inFile.read_short(2)
            firstEdge, numEdges = self.inFile.read_long(2)
            self.inFile.seek(56, 1)
            print "%d first edge" %firstEdge, numEdges
            
            face = []
            for j in range(firstEdge, firstEdge + numEdges):
                edge = surfedges[j]
                face.append(edge)
            verts = self.get_verts(meshName, face)
            self.create_face(meshName, i)
            self.add_face_verts(meshName, i, verts)
    
    def parse_file(self):
        '''Main parser method. Can be replaced'''
        
        #header
        
        magic = self.inFile.read_string(4)
        version = self.inFile.read_long()
        
        self.parse_lumps()
        mapRevision = self.inFile.read_long()
        
        #start parsing lumps. No particular order required
        print self.inFile.tell()
        meshName = "obj"
        self.create_object(meshName)
                           
        self.parse_vertices(meshName)
        self.parse_edges(meshName)
        self.parse_surfedges(meshName)
        self.parse_faces(meshName)
        self.parse_normals(meshName)
        self.parse_normal_index(meshName)
        
def read_file(path):
    '''Read the file'''
    
    openFile = StructReader(open(path, 'rb'))
    obj = Vindictus_BSP(inFile=openFile)
    obj.parse_file()
    openFile.close()
    return obj

def write_file(path):
    
    pass

def definitions():
    '''Return the header, extension, and a description of the format'''
    
    return "VBSP", "BSP", "Vindictus BSP"

if __name__ == '__main__':
    
    file1 = "lobby_beautyshop.bsp"
    obj = read_file(file1)